#include <boost/python.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include "UserApiMgr.h"
#include "InvestorAccount.h"
#include "Trader.h"
#include "Market.h"

BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(GetTraderById, GetTrader, 1, 1)
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(GetTraderByUidSid, GetTrader, 2, 2)

BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(GetMarketById, GetMarket, 1, 1)
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(GetMarketByUidSid, GetMarket, 2, 2)

BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PortfolioGetOrders, GetOrders, 0, 1)
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PortfolioGetTrades, GetTrades, 0, 1)


bool operator == (const InvestorPosition& p1, const InvestorPosition& p2)
{
	return p1.InstrumentID == p2.InstrumentID
		&& p1.PositionDate == p2.PositionDate
		&& p1.PosiDirection == p2.PosiDirection;
}

BOOST_PYTHON_MODULE(ServiceLib)
{
	using namespace boost::python;

	enum_<EnumIdCardType>("EnumIdCardType")
		.value("ICT_IDCard", ICT_IDCard)
		.value("ICT_Passport", ICT_Passport)
		;


	class_<std::vector<boost::shared_ptr<InvestorPosition> >, 
		boost::shared_ptr<std::vector<boost::shared_ptr<InvestorPosition> > > >("InvestorPositionPtrVector")
		.def(vector_indexing_suite<std::vector<boost::shared_ptr<InvestorPosition> >,true >());

	class_<std::map<std::string, boost::shared_ptr<InvestorPosition> >,
		boost::shared_ptr<std::map<std::string, boost::shared_ptr<InvestorPosition> > > >("InvestorPositionPtrMap")
		.def(map_indexing_suite<std::map<std::string, boost::shared_ptr<InvestorPosition> >, true >());

	class_<std::vector<InvestorPosition>,
		boost::shared_ptr<std::vector<InvestorPosition> > >("InvestorPositionVector")
		.def(vector_indexing_suite<std::vector<InvestorPosition> >());




	class_<std::vector<boost::shared_ptr<InputOrder> >,
		boost::shared_ptr<std::vector<boost::shared_ptr<InputOrder> > > >("InputOrderPtrVector")
		.def(vector_indexing_suite<std::vector<boost::shared_ptr<InputOrder> >, true >());

	class_<std::map<std::string, boost::shared_ptr<InputOrder> >,
		boost::shared_ptr<std::map<std::string, boost::shared_ptr<InputOrder> > > >("InputOrderPtrMap")
		.def(map_indexing_suite<std::map<std::string, boost::shared_ptr<InputOrder> >, true >());



	class_<std::vector<boost::shared_ptr<Order> >,
		boost::shared_ptr<std::vector<boost::shared_ptr<Order> > > >("OrderPtrVector")
		.def(vector_indexing_suite<std::vector<boost::shared_ptr<Order> >,true >());


	class_<std::map<std::string, boost::shared_ptr<Order> >,
		boost::shared_ptr<std::map<std::string, boost::shared_ptr<Order> > > >("OrderPtrMap")
		.def(map_indexing_suite<std::map<std::string, boost::shared_ptr<Order> >, true >());

	class_<std::map<std::string, Order >,
		boost::shared_ptr<std::map<std::string, Order > > >("OrderMap")
		.def(map_indexing_suite<std::map<std::string, Order > >());



	class_<std::vector<boost::shared_ptr<InputOrderAction> >,
		boost::shared_ptr<std::vector<boost::shared_ptr<InputOrderAction> > > >("InputOrderActionPtrVector")
		.def(vector_indexing_suite<std::vector<boost::shared_ptr<InputOrderAction> >, true >());

	class_<std::map<std::string, boost::shared_ptr<InputOrderAction> >,
		boost::shared_ptr<std::map<std::string, boost::shared_ptr<InputOrderAction> > > >("InputOrderActionPtrMap")
		.def(map_indexing_suite<std::map<std::string, boost::shared_ptr<InputOrderAction> >, true >());

	class_<std::map<std::string, InputOrderAction >,
		boost::shared_ptr<std::map<std::string, InputOrderAction > > >("InputOrderActionMap")
		.def(map_indexing_suite<std::map<std::string, InputOrderAction > >());


	class_<std::vector<boost::shared_ptr<Trade> >, 
		boost::shared_ptr<std::vector<boost::shared_ptr<Trade> > > >("TradePtrVector")
		.def(vector_indexing_suite<std::vector<boost::shared_ptr<Trade> >,true >());

	class_<std::map<std::string,boost::shared_ptr<Trade> >,
		boost::shared_ptr<std::map<std::string,boost::shared_ptr<Trade> > > >("TradePtrMap")
		.def(map_indexing_suite<std::map<std::string,boost::shared_ptr<Trade> >, true >());

	class_<std::map<std::string, Trade >,
		boost::shared_ptr<std::map<std::string, Trade > > >("TradeMap")
		.def(map_indexing_suite<std::map<std::string, Trade > >());

	class_<Portfolio, boost::shared_ptr<Portfolio>, boost::noncopyable>("Portfolio", no_init)
		

		.def("GetOrders", &Portfolio::GetOrders, PortfolioGetOrders(args("bHistory"),
		"Get Investor Today Orders if bHistory is true"))

		.def("GetTrades", &Portfolio::GetTrades, PortfolioGetTrades(args("bHistory")))

		.def("GetInputOrders", &Portfolio::GetInputOrders)

		.def("GetInputOrderActions", &Portfolio::GetInputOrderActions)

		.def("GetTradingAccounts", &Portfolio::GetTradingAccounts)

		

		.def("GetPositions", &Portfolio::GetPositions)
		;

	class_<InvestorAccount, boost::shared_ptr<InvestorAccount>, boost::noncopyable, bases<Portfolio> >("InvestorAccount", no_init)
		.def("GetInvestor", &InvestorAccount::GetInvestor)
		.def("GetSettlementInfo", &InvestorAccount::GetSettlementInfo);

	enum_<EnumMarginPrice>("EnumMarginPrice")
		.value("MPT_PreSettlementPrice", MPT_PreSettlementPrice)
		.value("MPT_SettlementPrice", MPT_SettlementPrice)
		.value("MPT_AveragePrice", MPT_AveragePrice)
		.value("MPT_OpenPrice", MPT_OpenPrice)
		;

	enum_<EnumAlgorithm>("EnumAlgorithm")
		.value("AG_All", AG_All)
		.value("AG_OnlyLost", AG_OnlyLost)
		.value("AG_OnlyGain", AG_OnlyGain)
		.value("AG_None", AG_None)
		;

	enum_<EnumIncludeCloseProfit>("EnumIncludeCloseProfit")
		.value("ICP_Include", ICP_Include)
		.value("ICP_NotInclude", ICP_NotInclude)
		;

	class_<BrokerTradingParams, boost::shared_ptr<BrokerTradingParams> >("BrokerTradingParams")
		.def_readwrite("MarginPriceType", &BrokerTradingParams::MarginPriceType)
		.def_readwrite("Algorithm", &BrokerTradingParams::Algorithm)
		.def_readwrite("AvailIncludeCloseProfit", &BrokerTradingParams::AvailIncludeCloseProfit)
		.def_readwrite("CurrencyID", &BrokerTradingParams::CurrencyID)
		.def_readwrite("OptionRoyaltyPriceType", &BrokerTradingParams::OptionRoyaltyPriceType)
		;

	class_<Trader,boost::shared_ptr<Trader>,boost::noncopyable>("trader", no_init)
		.def("UserID", &Trader::UserID)
		.def("Id",&Trader::Id)
		.def("BrokerID",&Trader::BrokerID)
		.def("GetUser", &Trader::GetUser, return_value_policy<reference_existing_object>())
		.def("GetServer", &Trader::GetServer, return_value_policy<reference_existing_object>())
		.def("LastError", &Trader::LastError, return_value_policy<copy_const_reference>())
		.def("GetInvestorAccount", &Trader::GetInvestorAccount)
		.def("GetBrokerTradingParams", &Trader::GetBrokerTradingParams)
		.def("GetTradingDay",&Trader::GetTradingDay);

	class_<std::map<std::string, boost::shared_ptr<Trader> > >("TraderPtrMap")
		.def(map_indexing_suite<std::map<std::string, boost::shared_ptr<Trader> >,true >());

	class_<std::map<std::string, boost::shared_ptr<Market> > >("MarketPtrMap")
		.def(map_indexing_suite<std::map<std::string, boost::shared_ptr<Market> >,true >());

	class_<UserApiMgr,boost::noncopyable >("UserApiMgr",no_init)
		.def("GetTrader", 
		static_cast<boost::shared_ptr<Trader>(UserApiMgr::*)(const std::string&)>(&UserApiMgr::GetTrader),
		GetTraderById())
		.def("GetTrader",
		static_cast<boost::shared_ptr<Trader>(UserApiMgr::*)(const std::string&,const std::string&)>(&UserApiMgr::GetTrader),
		GetTraderByUidSid())
		.def("GetMarket",
		static_cast<boost::shared_ptr<Market>(UserApiMgr::*)(const std::string&)>(&UserApiMgr::GetMarket),
		GetMarketById())
		.def("GetMarket",
		static_cast<boost::shared_ptr<Market>(UserApiMgr::*)(const std::string&, const std::string&)>(&UserApiMgr::GetMarket),
		GetMarketByUidSid())
		.def("GetTraders", &UserApiMgr::GetTraders, return_value_policy<reference_existing_object>())
		.def("GetMarkets", &UserApiMgr::GetMarkets, return_value_policy<reference_existing_object>())
		.def("GetInstance", &UserApiMgr::GetInstance, return_value_policy<reference_existing_object>())
		.staticmethod("GetInstance")
		;
}
